/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       mouse.cpp
 * Author:     karooolek
 * Created on: 2009-01-05
 *
 **********************************************************************************************************************/

#include "mouse.h"

namespace mGameEngine
{
namespace Input
{

Vector3 Mouse::_mpos;
uint8 Mouse::_buttons[8];
List<MouseListener *> Mouse::_listeners;

void Mouse::_glutMouseFunc(int btn, int state, int, int)
{
    ++btn;

    // button down
    if(state == 0)
    {
        _buttons[btn] = 2;

        for(List<MouseListener *>::Iterator i = _listeners.begin(); i != _listeners.end(); ++i)
        {
            MouseListener *l = *i;
            l->mouseButtonDown(MouseButton(btn));
        }
    }
    // button up
    else if(state == 1)
    {
        _buttons[btn] = 0;

        for(List<MouseListener *>::Iterator i = _listeners.begin(); i != _listeners.end(); ++i)
        {
            MouseListener *l = *i;
            l->mouseButtonUp(MouseButton(btn));
        }
    }
}

void Mouse::_glutMouseMotionFunc(int x, int y)
{
    Vector3 oldmpos(_mpos);

    _mpos.x = x;
    _mpos.y = glutGet(GLUT_WINDOW_HEIGHT) - y - 1;
    glReadPixels(int(_mpos.x), int(_mpos.y), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &_mpos.z);

    for(List<MouseListener *>::Iterator i = _listeners.begin(); i != _listeners.end(); ++i)
    {
        MouseListener *l = *i;
        l->mouseMoved(_mpos - oldmpos);
    }
}

bool Mouse::isButtonDown(MouseButton btn)
{
    return _buttons[btn] > 0;
}

MouseButton Mouse::getAnyButtonDown()
{
    uint8 btn;
    for(btn = 7; _buttons[btn] == 0 && btn != MOUSE_BTN_NONE; --btn);
    return MouseButton(btn);
}

const Vector3 &Mouse::getPosition()
{
    return _mpos;
}

void Mouse::setPosition(const Vector3 &position)
{
    glutWarpPointer(int(position.x), int(position.y));
}

void Mouse::addListener(MouseListener *listener)
{
    if(!listener)
    {
        return;
    }

    _listeners.push_back(listener);
    _listeners.unique();
}

void Mouse::removeListener(MouseListener *listener)
{
    _listeners.remove(listener);
}

}
}
